package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"time"
)

// WeChatMessage 结构体定义企业微信消息结构
type WeChatMessage struct {
	MsgType  string         `json:"msgtype"`
	Markdown WeChatMarkdown `json:"markdown"`
}

// WeChatMarkdown 结构体定义企业微信 Markdown 内容
type WeChatMarkdown struct {
	Content string `json:"content"`
}

// Alert 结构体用于解析Alertmanager传递的JSON数据
type Alert struct {
	Status       string            `json:"status"`
	Labels       map[string]string `json:"labels"`
	Annotations  map[string]string `json:"annotations"`
	StartsAt     time.Time         `json:"startsAt"`
	EndAt        time.Time         `json:"endsAt"`
	GeneratorURL string            `json:"generatorURL"`
}

// WebhookHandler 处理Alertmanager webhook的HTTP处理器
func WebhookHandler(w http.ResponseWriter, r *http.Request) {
	// 读取请求体
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Failed to read request body", http.StatusBadRequest)
		return
	}
	// 解析JSON数据
	var alert map[string]interface{}
	if err := json.Unmarshal(body, &alert); err != nil {
		fmt.Println("Failed to parse JSON data. Error:", err)
		fmt.Println("JSON data:", string(body))
		http.Error(w, "Failed to parse JSON data", http.StatusBadRequest)
		return
	}
	// 处理Alerts
	// 注意这里使用 alert["alerts"] 获取 alerts 数组
	alertsInterface, ok := alert["alerts"].([]interface{})
	if !ok {
		fmt.Println("Failed to extract alerts from JSON data")
		http.Error(w, "Failed to extract alerts from JSON data", http.StatusBadRequest)
		return
	}
	// 获取查询参数中的 token
	token := r.URL.Query().Get("token")
	if token == "" {
		http.Error(w, "Missing token parameter", http.StatusBadRequest)
		return
	}
	for _, rawAlert := range alertsInterface {
		// 转换每个 alert 为字节切片
		alertBytes, err := json.Marshal(rawAlert)
		if err != nil {
			fmt.Println("Failed to convert alert to bytes. Error:", err)
			continue
		}
		// 解析每个 alert
		var parsedAlert Alert
		if err := json.Unmarshal(alertBytes, &parsedAlert); err != nil {
			fmt.Println("Failed to parse alert. Error:", err)
			continue
		}
		// 在这里添加你的处理逻辑，例如发送通知、记录日志等
		fmt.Println(parsedAlert)
		sendWeChatMessage(parsedAlert, token)
	}
	// 返回成功响应
	w.WriteHeader(http.StatusOK)
	w.Write([]byte("Webhook received successfully"))
}

// sendWeChatMessage 发送企业微信消息
func sendWeChatMessage(alert Alert, token string) {
	// 根据告警状态设置标题颜色
	var titleColor string
	var message = WeChatMessage{}
	var duration, totalDuration string

	// 计算告警持续时长
	duration = time.Since(alert.StartsAt).Round(time.Second).String()
	// 计算告警总时长
	totalDuration = alert.EndAt.Sub(alert.StartsAt).Round(time.Second).String()

	if alert.Status == "firing" {
		titleColor = "<font color=\"warning\">**【告警发生】: **" + alert.Annotations["summary"] + "</font>"
		// 构造企业微信消息
		message = WeChatMessage{
			MsgType: "markdown",
			Markdown: WeChatMarkdown{
				Content: fmt.Sprintf("%s\n>**告警程序:** %s\n**告警节点:** %s\n**告警级别:** %s\n**告警详情:** %s\n**告警链接:** %s\n**告警时间:** %s\n**告警持续:** %s",
					titleColor, alert.Labels["job"], alert.Labels["instance"], alert.Labels["severity"], alert.Annotations["description"], alert.GeneratorURL, alert.StartsAt.In(time.FixedZone("CST", 8*60*60)).Format("2006-01-02 15:04:05"), duration),
			},
		}
	} else if alert.Status == "resolved" {
		titleColor = "<font color=\"info\">**【告警恢复】: **" + alert.Annotations["summary"] + "</font>"
		// 构造企业微信消息
		message = WeChatMessage{
			MsgType: "markdown",
			Markdown: WeChatMarkdown{
				Content: fmt.Sprintf("%s\n>**告警程序:** %s\n**告警节点:** %s\n**告警级别:** %s\n**告警详情:** %s\n**告警时间:** %s\n**恢复时间:** %s\n**告警时长:** %s",
					titleColor, alert.Labels["job"], alert.Labels["instance"], alert.Labels["severity"], alert.Annotations["description"], alert.StartsAt.In(time.FixedZone("CST", 8*60*60)).Format("2006-01-02 15:04:05"), alert.EndAt.In(time.FixedZone("CST", 8*60*60)).Format("2006-01-02 15:04:05"), totalDuration),
			},
		}
	} else {
		fmt.Printf("未知告警状态: %s", alert.Status)
		return
	}

	// 转换消息为JSON
	jsonMessage, err := json.Marshal(message)
	if err != nil {
		fmt.Println("Failed to marshal WeChat message:", err)
		return
	}
	// 发送POST请求到企业微信 webhook
	webhookURL := "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + token
	resp, err := http.Post(webhookURL, "application/json", bytes.NewBuffer(jsonMessage))
	if err != nil {
		fmt.Println("Failed to send WeChat message:", err)
		return
	}
	defer resp.Body.Close()
	// 读取响应
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Failed to read WeChat response:", err)
		return
	}
	fmt.Println("WeChat response:", string(respBody))
}

func main() {
	// 默认端口
	port := "8082"
	// 解析命令行参数
	for i := 0; i < len(os.Args); i++ {
		if os.Args[i] == "--port" && i+1 < len(os.Args) {
			port = os.Args[i+1]
			i++ // 跳过下一个参数
		}
	}

	// 设置HTTP路由和处理器
	http.HandleFunc("/alert", WebhookHandler)
	// 启动HTTP服务器，监听指定端口
	fmt.Printf("Alertmanager Webhook Server listening on :%s\n", port)
	http.ListenAndServe("0.0.0.0:"+port, nil)
}
